/*******************************************************************
 * Author	: Harsh and Maulik
 * Description	: It will implement shanons formula
 * Last Updated	: 13th Sept, 2011
 *******************************************************************/



#include "BDD.h"

extern int id;


int condition(char *pch,char *result, char *var, char c)
{


	if(pch == NULL)
		return 0;

	if((result[pch+strlen(var)-result] == c) || (result[pch+strlen(var)-result] =='\0'))
	{
			if((result-pch == 0) || (result[pch-result-1] ==c)|| (result[pch-result-1] == '~'))
				return 0;
	}

	return 1;
}

void showIndex(graph *g)
{
	int i =0;
	while(g->variables[i] != NULL)
	{
		printf("%s\t%d\n",g->variables[i],i+1);
		i++;
	}
}

void changeIndex(graph *g)
{	
	int i =0, index = 0;
	char temp[1000],d[1000];
	
	printf("Please Enter New Index\n");
	scanf("%d",&index);

	printf("Please Enter Variable\n");
	scanf("%s",d);
	
	if(index > g->totVar)
	{
		printf("Can't change new index is higher than total number of variables \n");
		return;
	}


	printf("Current Index\n");
	showIndex(g);
	printf("------------------------------------------\n");
	printf("Changed Index\n");
	strcpy(temp,g->variables[index -1]);

	while( strcmp(g->variables[i], d))
		i++;

	strcpy(g->variables[i],temp);
	strcpy(g->variables[index-1],d);
	showIndex(g);
}


char *refine(char *result)
{
         char *ans = (char *) malloc (strlen(result));
         *ans = '\0';
         int i = 0, j= 0;

         for(;*(result+i) != '\0';i++)
         {
                 if((*(result+i) == '0') &&  (!condition((result+i),result,"0", '+')))
                 {
                         if(*(result+i+1) == '\0')
			{
				 if(j != 0)
                                 	ans[j-1] = '\0';
                                 i++;
			}
                         else
                                 i=i++;
                 } else  {
                         ans[j] = *(result+i);
                         j++;
                 }
         }
         if(strlen(ans) == 0)
                strcpy(ans,"0");
 
 
         return ans;
         
}




char *expression(char *result /* The original expression */, char *variables)
{	
	char *ans = (char *) malloc (strlen(result));
	char *pch;
	int written=0;




	pch = (char *) strstr(result,variables);
	while((pch != NULL) && (result[pch+strlen(variables)-result] !='.') && (result[pch+strlen(variables)-result] !='\0'))
        {
			pch++;
                        pch = (char *) strstr(pch,variables);
        }

	written = pch-result;

// TO remove '.'before our variable. But we have to be careful we aare not removing if it is first variable
// or else segmentation fault will be there.
// If we are not wrting '.' then we must not constder it as written. So decreasing written.

	if(written)
	{
		strncpy(ans,result,pch-result-1);
		written--;
	}
	else
		strncpy(ans,result,pch-result);


	if(result[pch-result+strlen(variables)] != '\0')
	{
		if(written == 0)
			pch++;

		strncpy(ans+written, pch+strlen(variables), strlen(result)-written-strlen(variables)+1);
		
	}
	else
		ans[written] = '\0';

	if(strlen(ans)==0)
		strcat(ans,"1");

	return ans;
}





vertex *buildStep(char *argv, int index, graph *g)
{
	char low[1000] = "\0",high[1000] = "\0";
	char *result = NULL, *temp = NULL, *teq = NULL,*negate = NULL;
	char * pch;
	char delims[] = "+";
//	Argv is the equation.

	result = (char *)strtok( argv, delims );
	int number;
	int value;
	vertex* tempVertex;

	tempVertex = insertVertex(3,(index+1),g->variables[index],id);
	id++;


	while(result != NULL)
	{


		pch = (char *) strstr(result,g->variables[index]);
//		If pch is NULL i.e. given variable is not there in equation 		
// Error case: Like Harsh.a and we are looking for a than it will occur in a of Harsh
//For that we have to check that what is character after length of it.
// If it is '.' or '\0' than we are good to go.
// Still one error case remains ex. sha.a in that case even if we check for character after that there 
//is no use please check for that after.




		while( condition(pch, result, g->variables[index],'.'))
		{
			pch++;
			pch = (char *) strstr(pch,g->variables[index]);
		}

		if (pch == NULL)
		{  
			strcat(low,result);
			strcat(high,result);
			
		} else {

			
			// Now we will check whether not is applied or not
			if(result[pch-result-1] == '~') {
				temp = result;
				strcat(high,"0");
				
				negate = (char *) malloc (sizeof(g->variables[index])+1);
				negate[0] = '~';
				negate[1] = '\0';
				
				strcat(negate,g->variables[index]);
				teq = expression(temp,negate);
				strcat(low,teq);
				free(negate);



			} else {

				temp = result;
				strcat(low,"0");
	
				teq = expression(temp,g->variables[index]);
				strcat(high,teq);


			}

		}
		result = (char *)strtok( NULL, delims );


		if(result != NULL)
		{
			if(strlen(low) != 0)
				strcat(low,"+");
			if(strlen(high) != 0)
				strcat(high,"+");
		}


	}





	printf("Low equation is  :%s \n", low);

	pch = (char *) strstr(low,"1");
	while( condition(pch, low, "1",'+'))
        {
                        pch++;
                        pch = (char *) strstr(pch,"1");
        }



	if (pch != NULL )
		strcpy(low,"1");
	else
		strcpy(low,refine(low));
	printf("Refined low equation is  :%s \n", low);



	printf("High equation is :%s \n", high);

	pch = (char *) strstr(high,"1");
        while( condition(pch, high, "1",'+'))
        {
                        pch++;
                        pch = (char *) strstr(pch,"1");
        }

	if (pch != NULL )
		strcpy(high,"1");
	else
		strcpy(high,refine(high));

	printf("Refined high equation is :%s \n", high);

	index++;

	value = atoi(low);

	
	if( low[0] == '1' || low[0] == '0' )
	{   
		 tempVertex->low = insertVertex(value,((g->totVar)+1),"\0",id);
		id++;
	} else {
		tempVertex->low = buildStep(low, index,g);		
	}

	value = atoi(high);
	
	if( high[0] == '1' || high[0] == '0' )
	{	//Create Terminal vertex high
		tempVertex->high = insertVertex(value,((g->totVar)+1),"\0",id);
		id++;
	} else {
		tempVertex->high = buildStep(high, index,g);	
	}

	return tempVertex;
	
}





void build(graph *g,char * argv)
{
	g->root = buildStep(argv, 0, g);
}
